﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ChargeCard.Web.Models 
{
    public interface IVoucherRepository
    {
        IList<Voucher> FindVouchers(int provider, int priceType, int count);
        IList<Voucher> FindVouchers(int provider, int count);
        Voucher GetVoucherByPin(string pin);
        void ImportVouchers(IList<Voucher> vouchers);
        void DeleteVoucher(string pin);
        void Persist();
    }

    public class VoucherRepository : IVoucherRepository
    {
        private ChargeCardEntities db = new ChargeCardEntities();

        #region IVoucherRepository Members

        public IList<Voucher> FindVouchers(int provider, int priceType, int count)
        {
            IQueryable<Voucher> result = from v in db.Vouchers
                                         where v.PriceTypeId == priceType && v.ProviderId == provider
                                         select v;
            
            return result.Take<Voucher>(count).ToList<Voucher>();
        }

        public IList<Voucher> FindVouchers(int provider, int count)
        {
            IQueryable<Voucher> result = from v in db.Vouchers
                                         where v.ProviderId == provider
                                         select v;

            return result.Take<Voucher>(count).ToList<Voucher>();
        }

        public Voucher GetVoucherByPin(string PlainPin)
        {
            string pin = Voucher.EncryptPin(PlainPin);
            return db.Vouchers.SingleOrDefault<Voucher>(v => v.Pin == pin);
        }

        public void ImportVouchers(IList<Voucher> vouchers)
        {
            IList<string> pins = vouchers.Select(v => v.Pin).ToList<string>();
            IQueryable<Voucher> duplicates = from v in db.Vouchers
                                             where pins.Contains(v.Pin)
                                             select v;

            if (duplicates.Count() != 0)
            {
                throw new DuplicatePinException(duplicates.ToList<Voucher>()[0].PlainPIN);
            }

            foreach (Voucher v in vouchers)
            {
                db.AddToVouchers(v);
            }
        }

        public void DeleteVoucher( string PlainPin ) {
            db.DeleteObject(this.GetVoucherByPin(PlainPin));
        }

        public void Persist()
        {
            db.SaveChanges();
        }

        #endregion
    }

    public class DuplicatePinException : Exception
    {
        public String Pin { get; set; }

        public DuplicatePinException(string pin)
            : base("Duplicate Pin Number found!")
        {
            this.Pin = pin;
        }
    }
}
